Skip to main content

04 - 开卡与训练观测

这一篇是开卡之后到训练结束之间的操作。从这里开始每分钟都在计费,所以顺序是定死的。

一、开机到开跑

六条命令,中间三处停下来确认。完整命令在 llm-training-lab 的 README 里。

三处确认点,每一处都是「不确认就可能白跑三小时」:

停在哪要看到什么看不到怎么办
量完基线四层分数都记进表了没记就别往下走,训完再补测要多付一次冷启动
核对掩码参与 loss 20–40%,逐段标记正确03 篇二节tagstemplate
冒烟跑完显存峰值离 24G 有余量、loss 在动、checkpoint-10 真的存下来了第三条最容易漏 —— 它是实例被回收时你唯一的退路
vLLM 别关

量完基线不要停掉 vLLM,--gpu-memory-utilization 0.55 已经给训练留好了显存。关掉再起要重付十分钟冷启动。

如果训练启动时 OOM,先把 per_device_train_batch_size 降到 1、gradient_accumulation_steps 提到 16,再考虑动 vLLM。

二、训练时要同时盯三层

只看一层会漏,这是这一篇最重要的一句话。

三层不是三个可选项,是三个互补的视角。上面这个故障只有行为层能发现 —— 因为 loss 衡量的是「预测下一个 token 的准确度」,不是「输出结构对不对」,结构崩了它照样可以很低。

2.1 曲线层:用哪个面板

LlamaFactory 的 report_to 支持四种,选哪个不影响训练本身,只影响你看曲线的体验:

选项是什么什么时候选它
wandbWeights & Biases,这类工具的事实标准默认选它。 生态最广、教程最多,个人用免费
swanlab国产开源替代,接口和 wandb 基本一致,可自托管机器在国内、或者连不上 api.wandb.ai
tensorboard本地起服务看,不上传不想让训练数据出机器
none只有终端日志冒烟跑够用了

这三个的差别在能不能连上,不在功能。 你的机器直连国外,wandb 没有障碍;SwanLab 的主要优势是国内访问快,对你不成立。

export WANDB_API_KEY=...
export WANDB_PROJECT=agent-sft # 不设的话所有 run 会堆进 huggingface 这个默认项目
llamafactory-cli train qwen3_4b_lora_sft.yaml
每轮给 run 起个能认出来的名字
export WANDB_NAME="r1-rank16-lr1e4-6k"

第二轮回来对比时,run-20260904_031522 这种默认名你分不清哪个是哪个。把这一轮改动的那个变量写进名字里,是最省事的实验记录。

四条曲线,各自回答一个问题:

曲线回答异常长什么样
train loss在学吗平的、或者往上走
val loss学过头了吗开始抬头,而 train loss 还在降
grad norm稳吗突刺 —— 它比 loss 早一步,是最有用的预警
token/s 吞吐卡在哪忽高忽低说明数据加载跟不上

grad norm 那条最值得盯。 loss 崩掉之前它通常先跳一次,那时候杀掉改学习率还来得及;等 loss 崩了再动手,已经浪费了一段机时。

2.2 机器层:nvidia-smi

watch -n 5 nvidia-smi

GPU 利用率长期低于 80%,说明你在为 CPU 的慢付 GPU 的钱。 常见原因是 dataloader_num_workers 太小,或者机器 CPU 核数少(这也是 01 篇 7.1 要确认 CPU 配置的原因)。

显存峰值要留意的是波动:某条特别长的样本、某次梯度检查点没配好,都会顶上去一截。冒烟跑时看到的峰值不等于正式训练的峰值。

2.3 行为层:把模型的原始输出打出来看

这一层最容易漏,也最不能漏。

真实会发生的情况:train loss 一路降到 0.3,曲线漂亮,但模型输出的 tool call 已经不是合法 JSON 了。曲线上完全没有征兆 —— 因为 loss 衡量的是「预测下一个 token 的准确度」,不是「输出结构对不对」。

python probe.py saves/qwen3-4b-agent/lora/sft --watch

它盯着输出目录,每出一个新 checkpoint 就在三个固定 prompt 上生成一遍,原样打印。三个探针各测一件事:

探针测什么
「查一下华东区 8 月的订单」最基本的单轮,这条崩了说明格式坏了
「你好,你是谁?」不该调工具,测有没有养成滥用工具的习惯
「查华东地区 8 月的订单」region 写法非法,测报错恢复学到没有

prompt 必须固定。 换了 prompt 就没法比较不同 step 之间的变化,这一层的价值就没了。

三、loss 曲线四种病态形状

形状多半是什么处置
一直是平的学习率太小,或者 LoRA 没真的挂上杀。检查 lora_target,确认日志里打印的可训练参数量不是 0
降到某处突然飙升学习率太大杀。lr 降一半,从最近的 checkpoint 续训
抖得很厉害但整体在降等效 batch 太小不用杀。把 gradient_accumulation_steps 提上去,下一轮再说
train 降、val 抬头过拟合不用杀。记下抬头的 step,用那之前的 checkpoint

前两种杀,后两种不杀。 判断依据是「继续跑下去还有没有可用产物」——抖动和过拟合都还能拿到能用的 checkpoint,平和飙升拿不到。

四、被回收了怎么办

抢占式实例随时可能没。配置里 save_steps: 100 就是为这个。

# 把 resume_from_checkpoint 填成最后一个 checkpoint,命令其余部分不变
llamafactory-cli train qwen3_4b_lora_sft.yaml \
--resume_from_checkpoint saves/qwen3-4b-agent/lora/sft/checkpoint-400

续训后第一件事是看 loss 曲线接得上不上。接不上说明数据顺序或随机种子没恢复,那段训练是废的。

五、记下来

机器型号 / CUDA / vLLM 版本待填
实际 cutoff_len / batch / 累积步数待填
显存峰值待填
GPU 平均利用率待填
总步数 / 总时长待填
val loss 最低点在第几步待填
中途杀过几次、为什么待填
本轮机时与花费待填

倒数第二行最有价值。 它决定下一轮 num_train_epochs 该设多少 —— 这是唯一一个必须靠实测才知道的超参。